home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gas / gassrc02.zoo / app.c < prev    next >
C/C++ Source or Header  |  1992-04-27  |  8KB  |  405 lines

  1. /* This is the Assembler Pre-Processor
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* App, the assembler pre-processor.  This pre-processor strips out excess
  21.    spaces, turns single-quoted characters into a decimal constant, and turns
  22.    # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  23.    This needs better error-handling.
  24.  */
  25. #include <stdio.h>
  26. #ifdef USG
  27. #define bzero(s,n) memset(s,0,n)
  28. #endif
  29. #if !defined(__STDC__) && !defined(const)
  30. #define const /* Nothing */
  31. #endif
  32.  
  33. static char    lex [256];
  34. static const char    symbol_chars[] = 
  35.     "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  36.  
  37. extern const char comment_chars[];
  38. extern const char line_comment_chars[];
  39.  
  40. #define LEX_IS_SYMBOL_COMPONENT        (1)
  41. #define LEX_IS_WHITESPACE        (2)
  42. #define LEX_IS_LINE_SEPERATOR        (4)
  43. #define LEX_IS_COMMENT_START        (8)    /* JF added these two */
  44. #define LEX_IS_LINE_COMMENT_START    (16)
  45. #define IS_SYMBOL_COMPONENT(c)        (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  46. #define IS_WHITESPACE(c)        (lex [c] & LEX_IS_WHITESPACE)
  47. #define IS_LINE_SEPERATOR(c)        (lex [c] & LEX_IS_LINE_SEPERATOR)
  48. #define IS_COMMENT(c)            (lex [c] & LEX_IS_COMMENT_START)
  49. #define IS_LINE_COMMENT(c)        (lex [c] & LEX_IS_LINE_COMMENT_START)
  50.  
  51. void
  52. do_scrub_begin()
  53. {
  54.     const char *p;
  55.  
  56.     bzero (lex, sizeof(lex));        /* Trust NOBODY! */
  57.     lex [' ']        |= LEX_IS_WHITESPACE;
  58.     lex ['\t']        |= LEX_IS_WHITESPACE;
  59.     for (p =symbol_chars;*p;++p)
  60.         lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  61.     lex ['\n']        |= LEX_IS_LINE_SEPERATOR;
  62. #ifdef DONTDEF
  63.     lex [':']        |= LEX_IS_LINE_SEPERATOR;
  64. #endif
  65.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  66.     for (p=comment_chars;*p;p++)
  67.         lex[*p] |= LEX_IS_COMMENT_START;
  68.     for (p=line_comment_chars;*p;p++)
  69.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  70. }
  71.  
  72. FILE *scrub_file;
  73.  
  74. int
  75. scrub_from_file()
  76. {
  77. #ifdef atarist
  78.     int c;
  79.     if((c = getc(scrub_file)) == '\r') c = getc(scrub_file);
  80.     return c;
  81. #else
  82.     return getc(scrub_file);
  83. #endif
  84. }
  85.  
  86. void
  87. scrub_to_file(ch)
  88. int ch;
  89. {
  90.     ungetc(ch,scrub_file);
  91. }
  92.  
  93. char *scrub_string;
  94. char *scrub_last_string;
  95.  
  96. int
  97. scrub_from_string()
  98. {
  99.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  100. }
  101.  
  102. void
  103. scrub_to_string(ch)
  104. int ch;
  105. {
  106.     *--scrub_string=ch;
  107. }
  108.  
  109. int
  110. do_scrub_next_char(get,unget)
  111. int (*get)();
  112. void (*unget)();
  113. /* FILE *fp; */
  114. {
  115.     /* State 0: beginning of normal line
  116.         1: After first whitespace on normal line (flush more white)
  117.         2: After first non-white on normal line (keep 1white)
  118.         3: after second white on normal line (flush white)
  119.         4: after putting out a .line, put out digits
  120.         5: parsing a string, then go to old-state
  121.         6: putting out \ escape in a "d string.
  122.         7: After putting out a .file, put out string.
  123.         8: After putting out a .file string, flush until newline.
  124.         -1: output string in out_string and go to the state in old_state
  125.         -2: flush text until a '*' '/' is seen, then go to state old_state
  126.     */
  127.  
  128.     static state;
  129.     static old_state;
  130.     static char *out_string;
  131.     static char out_buf[20];
  132.     static add_newlines;
  133.     int ch;
  134.  
  135.     if(state==-1) {
  136.         ch= *out_string++;
  137.         if(*out_string==0) {
  138.             state=old_state;
  139.             old_state=3;
  140.         }
  141.         return ch;
  142.     }
  143.     if(state==-2) {
  144.         for(;;) {
  145.             do ch=(*get)();
  146.             while(ch!=EOF && ch!='\n' && ch!='*');
  147.             if(ch=='\n' || ch==EOF)
  148.                 return ch;
  149.              ch=(*get)();
  150.              if(ch==EOF || ch=='/')
  151.                  break;
  152.             (*unget)(ch);
  153.         }
  154.         state=old_state;
  155.         return ' ';
  156.     }
  157.     if(state==4) {
  158.         ch=(*get)();
  159.         if(ch==EOF || (ch>='0' && ch<='9'))
  160.             return ch;
  161.         else {
  162.             while(ch!=EOF && IS_WHITESPACE(ch))
  163.                 ch=(*get)();
  164.             if(ch=='"') {
  165.                 (*unget)(ch);
  166.                 out_string="; .file ";
  167.                 old_state=7;
  168.                 state= -1;
  169.                 return *out_string++;
  170.             } else {
  171.                 while(ch!=EOF && ch!='\n')
  172.                     ch=(*get)();
  173.                 return ch;
  174.             }
  175.         }
  176.     }
  177.     if(state==5) {
  178.         ch=(*get)();
  179.         if(ch=='"') {
  180.             state=old_state;
  181.             return '"';
  182.         } else if(ch=='\\') {
  183.             state=6;
  184.             return ch;
  185.         } else if(ch==EOF) {
  186.             as_warn("End of file in string: inserted '\"'");
  187.              state=old_state;
  188.             (*unget)('\n');
  189.             return '"';
  190.         } else {
  191.             return ch;
  192.         }
  193.     }
  194.     if(state==6) {
  195.         state=5;
  196.         ch=(*get)();
  197.         switch(ch) {
  198.             /* This is neet.  Turn "string
  199.                more string" into "string\n  more string"
  200.              */
  201.         case '\n':
  202.             (*unget)('n');
  203.             add_newlines++;
  204.             return '\\';
  205.  
  206.         case '"':
  207.         case '\\':
  208.         case 'b':
  209.         case 'f':
  210.         case 'n':
  211.         case 'r':
  212.         case 't':
  213.         case '0':
  214.         case '1':
  215.         case '2':
  216.         case '3':
  217.         case '4':
  218.         case '5':
  219.         case '6':
  220.         case '7':
  221.             break;
  222.         default:
  223.             as_warn("Unknown escape '\\%c' in string: Ignored",ch);
  224.             break;
  225.  
  226.         case EOF:
  227.             as_warn("End of file in string: '\"' inserted");
  228.             return '"';
  229.         }
  230.         return ch;
  231.     }
  232.  
  233.     if(state==7) {
  234.         ch=(*get)();
  235.         state=5;
  236.         old_state=8;
  237.         return ch;
  238.     }
  239.  
  240.     if(state==8) {
  241.         do ch= (*get)();
  242.         while(ch!='\n');
  243.         state=0;
  244.         return ch;
  245.     }
  246.  
  247.  flushchar:
  248.     ch=(*get)();
  249.     switch(ch) {
  250.     case ' ':
  251.     case '\t':
  252.         do ch=(*get)();
  253.         while(ch!=EOF && IS_WHITESPACE(ch));
  254.         if(ch==EOF)
  255.             return ch;
  256.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  257.             (*unget)(ch);
  258.             goto flushchar;
  259.         }
  260. #ifdef CANON
  261.         if(ch==':') {
  262.             (*unget)(ch);
  263.             goto flushchar;
  264.         }
  265. #endif CANON
  266.         (*unget)(ch);
  267.         if(state==0 || state==2) {
  268.             state++;
  269.             return ' ';
  270.         } else goto flushchar;
  271.  
  272.     case '/':
  273.         ch=(*get)();
  274.         if(ch=='*') {
  275.             for(;;) {
  276.                 do {
  277.                     ch=(*get)();
  278.                     if(ch=='\n')
  279.                         add_newlines++;
  280.                 } while(ch!=EOF && ch!='*');
  281.                 ch=(*get)();
  282.                 if(ch==EOF || ch=='/')
  283.                     break;
  284.                 (*unget)(ch);
  285.             }
  286.             if(ch==EOF)
  287.                 as_warn("End of file in '/' '*' string: */ inserted");
  288.  
  289.             (*unget)(' ');
  290.             goto flushchar;
  291.         } else {
  292.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  293.                 (*unget)(ch);
  294.                 ch='/';
  295.                 goto deal_misc;
  296.             }
  297.             if(ch!=EOF)
  298.                 (*unget)(ch);
  299.             return '/';
  300.         }
  301.         break;
  302.  
  303.     case '"':
  304.         old_state=state;
  305.         state=5;
  306.         return '"';
  307.         break;
  308.  
  309.     case '\'':
  310.         ch=(*get)();
  311.         if(ch==EOF) {
  312.             as_warn("End-of-file after a ': \000 inserted");
  313.             ch=0;
  314.         }
  315.         sprintf(out_buf,"(%d)",ch&0xff);
  316.         old_state=state;
  317.         state= -1;
  318.         out_string=out_buf;
  319.         return *out_string++;
  320.  
  321.     case ':':
  322.         if(state!=3)
  323.             state=0;
  324.         return ch;
  325.  
  326.     case '\n':
  327.         if(add_newlines) {
  328.             --add_newlines;
  329.             (*unget)(ch);
  330.         }
  331.     case ';':
  332.         state=0;
  333.         return ch;
  334.  
  335.     default:
  336.     deal_misc:
  337.         if(state==0 && IS_LINE_COMMENT(ch)) {
  338.             do ch=(*get)();
  339.             while(ch!=EOF && IS_WHITESPACE(ch));
  340.             if(ch==EOF) {
  341.                 as_warn("EOF in comment:  Newline inserted");
  342.                 return '\n';
  343.             }
  344.             if(ch<'0' || ch>'9') {
  345.                 while(ch!=EOF && ch!='\n')
  346.                     ch=(*get)();
  347.                 if(ch==EOF)
  348.                     as_warn("EOF in Comment: Newline inserted");
  349.                 state=0;
  350.                 return '\n';
  351.             }
  352.             (*unget)(ch);
  353.             old_state=4;
  354.             state= -1;
  355.             out_string=".line ";
  356.             return *out_string++;
  357.  
  358.         } else if(IS_COMMENT(ch)) {
  359.             do ch=(*get)();
  360.             while(ch!=EOF && ch!='\n');
  361.             if(ch==EOF)
  362.                 as_warn("EOF in comment:  Newline inserted");
  363.             state=0;
  364.             return '\n';
  365.  
  366.         } else if(state==0) {
  367.             state=2;
  368.             return ch;
  369.         } else if(state==1) {
  370.             state=2;
  371.             return ch;
  372.         } else {
  373.             return ch;
  374.  
  375.         }
  376.     case EOF:
  377.         if(state==0)
  378.             return ch;
  379.         as_warn("End-of-File not at end of a line");
  380.     }
  381.     return -1;
  382. }
  383.  
  384. #ifdef TEST
  385.  
  386. char comment_chars[] = "|";
  387. char line_comment_chars[] = "#";
  388.  
  389. main()
  390. {
  391.     int    ch;
  392.  
  393.     app_begin();
  394.     while((ch=do_scrub_next_char(stdin))!=EOF)
  395.         putc(ch,stdout);
  396. }
  397.  
  398. as_warn(str)
  399. char *str;
  400. {
  401.     fputs(str,stderr);
  402.     putc('\n',stderr);
  403. }
  404. #endif
  405.